package java0.conc0303;

import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 本周作业：（必做）思考有多少种方式，在main函数启动一个新线程或线程池，
 * 异步运行一个方法，拿到这个方法的返回值后，退出主线程？
 * 写出你的方法，越多越好，提交到github。
 *
 * 一个简单的代码参考：
 */
public class Homework03 {
    
    public static void main(String[] args) throws ExecutionException, InterruptedException, BrokenBarrierException {
        
        long start=System.currentTimeMillis();

        // 在这里创建一个线程或线程池，
        // 异步执行 下面方法
        /**
         * 1.FutureTask
         */
//        FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
//            @Override
//            public Integer call() throws Exception {
//                return sum();
//            }
//        });
//        new Thread(task).start();
//        System.out.println("异步计算结果为："+task.get());
        /**
         * 2.FutureTask+ExecutorService
         */
//        ExecutorService executor = Executors.newSingleThreadExecutor();
//        FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
//            @Override
//            public Integer call() throws Exception {
//                return sum();
//            }
//        });
//        executor.submit(task);
//        System.out.println("异步计算结果为："+task.get());
        /**
         * 3.CountDownLatch
         */
//        CountDownLatch countDownLatch = new CountDownLatch(1);
//        ReentrantLock reentrantLock=new ReentrantLock();
//        AtomicInteger result = new AtomicInteger();
//        new Thread(() -> {
//            //确保在进程中sum被锁在Thread中
//            reentrantLock.lock();
//            result.set(sum());
//            reentrantLock.unlock();
//            countDownLatch.countDown();
//        }).start();
//        //确保堵塞主进程等Thread.countDown()后再输出结果
//        countDownLatch.await();
//        System.out.println("异步计算结果为："+result.get());
        /**
         * 4.CyclicBarrier
         */
//        CyclicBarrier cyclicBarrier=new CyclicBarrier(2);
//        ReentrantLock reentrantLock=new ReentrantLock();
//        AtomicInteger result = new AtomicInteger();
//        new Thread(() -> {
//            //确保在进程中sum被锁在Thread中
//            reentrantLock.lock();
//            result.set(sum());
//            reentrantLock.unlock();
//            try {
//                //确保main进程也await()后，大家都可以往下继续执行
//                cyclicBarrier.await();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            } catch (BrokenBarrierException e) {
//                e.printStackTrace();
//            }
//        }).start();
//        //因为new CyclicBarrier(2)，所以子线程Thread不执行await()将会一直堵塞
//        cyclicBarrier.await();
//        System.out.println("异步计算结果为："+result.get());
        /**
         * 5.LockSupport
         */
//        AtomicInteger result = new AtomicInteger();
//        ReentrantLock reentrantLock=new ReentrantLock();
//        Thread main = Thread.currentThread();
//        new Thread(() -> {
//            reentrantLock.lock();
//            result.set(sum());
//            reentrantLock.unlock();
//            //让main线程可以往下执行
//            LockSupport.unpark(main);
//        }).start();
//        //等待Thread线程允许往下执行
//        LockSupport.park();
//        System.out.println("异步计算结果为："+result.get());
        /**
         * 6.CompletableFuture
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            return sum();
//        });
//        System.out.println("异步计算结果为："+future.get());
        /**
         * 7.AtomicBoolean
         */
//        AtomicBoolean asyncBoolean=new AtomicBoolean(true);
//        AtomicInteger atomicInteger = new AtomicInteger();
//        new Thread(() -> {
//            atomicInteger.set(sum());
//            asyncBoolean.set(false);
//        }).start();
//        while(asyncBoolean.get())
//        {
//            //使用原子布尔类作为堵塞信号
//        }
//        // 确保  拿到result 并输出
//        System.out.println("异步计算结果为："+atomicInteger.get());
         
        System.out.println("使用时间："+ (System.currentTimeMillis()-start) + " ms");
        
        // 然后退出main线程
    }
    
    private static int sum() {
        return fibo(36);
    }
    
    private static int fibo(int a) {
        if ( a < 2) 
            return 1;
        return fibo(a-1) + fibo(a-2);
    }
}
